import { convertToModelMessages, createUIMessageStream, createUIMessageStreamResponse, generateText, streamText } from 'ai'
import type { UIMessage } from 'ai'
import { z } from 'zod'
import { createDeepSeek } from '@ai-sdk/deepseek';

const deepseek = createDeepSeek({
  apiKey: process.env.DEEPSEEK_API_KEY ?? '',
});

defineRouteMeta({
  openAPI: {
    description: 'Chat with AI.',
    tags: ['ai']
  }
})

export default defineEventHandler(async (event) => {
  const session = await getUserSession(event)

  const { id } = getRouterParams(event)

  // 根据前端传过来的信息解析成model，messages
  const body = await readValidatedBody(event, z.object({
    model: z.string(),
    messages: z.array(z.custom<UIMessage>())
  }).parse)

  const { model, messages } = body

  const db = useDrizzle()

  const chat = await db.query.chats.findFirst({
    where: (chat, { eq }) => and(eq(chat.id, id as string), eq(chat.userId, session.user?.id || session.id)),
    with: {
      messages: true
    }
  })

  if (!chat) {
    throw createError({ statusCode: 404, statusMessage: 'Chat not found' })
  }

  const lastMessage = messages[messages.length - 1]
  // 插入最后一条用户消息到数据库（排除已存在的消息）
  if (lastMessage?.role === 'user' && !chat.messages.some(m => m.parts === JSON.stringify(lastMessage.parts))) {
    await db.insert(tables.messages).values({
      chatId: id as string,
      role: 'user',
      parts: JSON.stringify(lastMessage.parts)
    })
  }

  // 使用大模型给message一个标题（在Agent调用后异步进行）
  let generatedTitle = null
  if (!chat.title) {
    try {
      const { text: title } = await generateText({
        model: deepseek('deepseek-chat'),
        system: `You are a title generator for a chat:
            - Generate a short title based on the first user's message
            - The title should be less than 30 characters long
            - The title should be a summary of the user's message
            - Do not use quotes (' or ") or colons (:) or any other punctuation
            - Do not use markdown, just plain text`,
        prompt: JSON.stringify(messages[0])
      })

      await db.update(tables.chats).set({ title }).where(eq(tables.chats.id, id as string))
      generatedTitle = title // 保存生成的标题，准备发送给前端
    } catch (error) {
      console.error('Failed to generate title:', error)
      // 标题生成失败不应该影响聊天功能
    }
  }

  // 先调用Agent，确保聊天正常开始
  const agentResponse = await fetch('http://127.0.0.1:5000/api/agent/chat', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      // 不需要鉴权
      // ...(process.env.AGENT_API_KEY ? { Authorization: `Bearer ${process.env.AGENT_API_KEY}` } : {})
    },
    body: JSON.stringify({
      chat_id: id,
      model,
      messages // UIMessage[] from the client
    })
  })

  if (!agentResponse.ok) {
    throw createError({ statusCode: 502, statusMessage: `Agent upstream error: ${agentResponse.status} ${agentResponse.statusText}` })
  }


  // 统一使用同一个流式响应，但根据是否有标题来决定是否发送标题更新
  return createUIMessageStreamResponse({
    stream: createUIMessageStream({
      execute: async ({ writer }) => {
        // 如果生成了新标题，先发送给前端
        if (generatedTitle) {
          writer.write({
            type: 'data-chat-title',
            data: { message: generatedTitle },
            transient: false
          })
        }

        // 读取原始流并重新格式化
        const reader = agentResponse.body?.getReader()
        if (!reader) return

        const decoder = new TextDecoder()

        try {
          while (true) {
            const { done, value } = await reader.read()
            if (done) break

            const chunk = decoder.decode(value, { stream: true })
            const lines = chunk.split('\n').filter(line => line.trim())

            for (const line of lines) {
              try {
                const data = JSON.parse(line)
                // 直接写入数据，因为您的FastAPI已经返回了正确格式
                writer.write(data)
              } catch (e) {
                console.error('Failed to parse line:', line)
              }
            }
          }
        } finally {
          reader.releaseLock()
        }
      },
      onFinish: async ({ messages}) => {
        // Optional: persist finalMessages to DB here if desired
        // e.g. await db.insert(tables.messages).values(...)
        await db.insert(tables.messages).values(messages.map(message => ({
          chatId: chat.id,
          role: message.role as 'user' | 'assistant',
          parts: JSON.stringify(message.parts)
        })))
      }
    })
  })
})
